<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <title>组件</title>
</head>
<body>
    <div id="ap">
        <runoob></runoob>
        <run></run>
        <child message="hello"></child>
        <input v-model="parent">
        <br/>
        <chil v-bind:message="parent"></chil>
        <br/>
        <div id="counter-event-example">
            <p>{{ total }}</p>
            <button-counter v-on:increment="incrementTotal"></button-counter>
            <button-counter v-on:increment="incrementTotal"></button-counter>
        </div>
    </div>
</body>
<script>
    // 组件可用来封装可重用的代码，以扩展 HTML 元素

    // 全局组件，runoob是组件名，后面是属性
    //注册
    Vue.component('runoob',{
        template:'<h1>全局组件</h1>'
    })
    // 创建根实例
    new Vue({
        el: '#ap'
    })

    //prop 是单向绑定的：当父组件的属性变化时，将传导给子组件，但是不会反过来
    // 父组件<child>的数据需要通过 props 把数据传给子组件<span>
    Vue.component('child',{
        props:['message'],
        template:'<span>{{message}}</span>'
    })
    new Vue({
        el:'#ap'
    })

    // 用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时，该变化也会传导给子组件
    Vue.component('chil',{
        props:['message'],
        template:'<span>{{message}}</span>'
    })
    new Vue({
        el:"#ap",
        data:{
            parent:"父组件内容"
        }
    })

    // Prop 验证
    Vue.component('example', {
    props: {
        // 基础类型检测 （`null` 意思是任何类型都可以）
        propA: Number,
        // 多种类型
        propB: [String, Number],
        // 必传且是字符串
        propC: {
        type: String,
        required: true
        },
        // 数字，有默认值
        propD: {
        type: Number,
        default: 100
        },
        // 数组／对象的默认值应当由一个工厂函数返回
        propE: {
        type: Object,
        default: function () {
            return { message: 'hello' }
        }
        },
        // 自定义验证函数
        propF: {
        validator: function (value) {
            return value > 10
      }
    }
  }
})

    //自定义事件
    // 父组件是使用 props 传递数据给子组件，但如果子组件要把数据传递回去，就需要使用自定义事件！
    Vue.component('button-counter', {
    template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
    data: function () {
        return {
        counter: 0
        }
    },
    methods: {
        incrementHandler: function () {
        this.counter += 1
        this.$emit('increment')
        }
    },
    })
    new Vue({
    el: '#counter-event-example',
    data: {
        total: 0
    },
    methods: {
        incrementTotal: function () {
        this.total += 1
        }
    }
    })

    //局部组件
    var Child = {
        template:'<h1>局部组件</h1>'
    }
    // 根实例
    new Vue({
        el:'#ap',
        data: {
            //<run>将只在根实例下使用
            'run':Child
        }
    })
</script>
</html>